
namespace EveIntel.WpfApplication.ViewModels
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.ComponentModel.Composition;
    using System.ComponentModel.Composition.Hosting;
    using System.IO;
    using System.Reflection;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Input;
    using API.Enums;
    using API.Interfaces;
    using Interfaces;
    using Views;

    public sealed class MainViewModel : ViewModelBase<IMainView>
    {
        private readonly ICommand _exitCommand = null;
        private readonly ICommand _searchCommand = null;
        private readonly ICommand _aboutCommand = null;

        private IEnumerable<string> _solarSystems;
        private ObservableCollection<Uri> _uris = null;
        private ObservableCollection<IIntelProvider> _plugins = null;

        private string _selectedSolarSystem;
        private string _player;

        /// <summary>
        /// Initializes a new instance
        /// </summary>
        public MainViewModel()
        {
            _uris = new ObservableCollection<Uri>();
            Task.Factory.StartNew(LoadSolarSystems);
            Task.Factory.StartNew(LoadProviders);
        }
        /// <summary>
        /// Initializes a new instance
        /// </summary>
        /// <param name="view">The view associated</param>
        public MainViewModel(IMainView view) : base(view)
        {
        }
        /// <summary>
        /// Obtains the Search ICommand
        /// </summary>
        public ICommand SearchCommand
        {
            get { return _searchCommand ?? new BindableCommand<object>(OnSearch); }
        }
        /// <summary>
        /// Obtains the Exit ICommand
        /// </summary>
        public ICommand ExitCommand
        {
            get { return _exitCommand ?? new BindableCommand<object>(OnExit); }
        }
        /// <summary>
        /// Obtains the About ICommand
        /// </summary>
        public ICommand AboutCommand
        {
            get { return _aboutCommand ?? new BindableCommand<object>(OnAbout); }
        }
       
        public IEnumerable<string> SolarSystems
        {
            get { return _solarSystems; }
            set { _solarSystems = value; InvokePropertyChanged(new PropertyChangedEventArgs("SolarSystems")); }
        }

        public string SelectedSolarSystem
        {
            get { return _selectedSolarSystem; }
            set { _selectedSolarSystem = value; InvokePropertyChanged(new PropertyChangedEventArgs("SelectedSolarSystem")); InvokePropertyChanged(new PropertyChangedEventArgs("CanSearch")); }
        }

        public string Player
        {
            get { return _player; }
            set { _player = value; InvokePropertyChanged(new PropertyChangedEventArgs("Player")); InvokePropertyChanged(new PropertyChangedEventArgs("CanSearch")); }
        }

        public bool CanSearch
        {
            get { return !string.IsNullOrEmpty(SelectedSolarSystem) || !string.IsNullOrEmpty(Player); } 
        }

        public ObservableCollection<Uri> SearchingUris
        {
            get { return _uris; }
            set { _uris = value; InvokePropertyChanged(new PropertyChangedEventArgs("SearchingUris")); }
        }

        [ImportMany(typeof(IIntelProvider), AllowRecomposition = false, RequiredCreationPolicy = CreationPolicy.Shared)]
        public ObservableCollection<IIntelProvider> Plugins
        {
            get { return _plugins; }
            set { _plugins = value; InvokePropertyChanged(new PropertyChangedEventArgs("Plugins")); }
        }

        private void LoadProviders()
        {
            using (var catalog = new AggregateCatalog())
            using (var container = new CompositionContainer(catalog))
            using (var directoryCatalog = new DirectoryCatalog(".\\IntelProviders", "*.dll"))
            {
                catalog.Catalogs.Add(directoryCatalog);
                container.ComposeParts(this);
            }
        }

        private void OnSearch(object value)
        {
            SearchingUris.Clear();
            foreach (var provider in Plugins)
            {
                try
                {
                    if(!string.IsNullOrEmpty(SelectedSolarSystem) && provider!=null && provider.CanProvideIntel(IntelTypeEnum.SolarSystem))
                    {
                        var uri = provider.GetUri(IntelTypeEnum.SolarSystem, new string[] { SelectedSolarSystem });
                        if (uri != null)
                            SearchingUris.Add(uri);    
                    }

                    if (!string.IsNullOrEmpty(Player) && provider != null && provider.CanProvideIntel(IntelTypeEnum.Player))
                    {
                        var uri = provider.GetUri(IntelTypeEnum.Player, new string[] { Player });
                        if (uri != null)
                            SearchingUris.Add(uri);    
                    }
                }
                catch (Exception)
                {
                }
            }
        }

        private void OnAbout(object value)
        {
            var vm = new AboutViewModel(new AboutView());
            vm.View.ShowDialog((Window) View);
        }

        private void OnExit(object value)
        {
            View.Close();
        }

        private void LoadSolarSystems()
        {
            string[] content = null;
            using(var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("EveIntel.WpfApplication.Data.systems.txt"))
            using(var reader = new StreamReader(stream, Encoding.UTF8))
            {
                content = reader.ReadToEnd().Split(new char[]{','});
            }

            SolarSystems = new List<string>(content);
        }

    }
}